#include "queue.h"

Queue *queue_create(const uint32_t capacity) {
    Queue *queue = (Queue*)malloc(sizeof(Queue));
    if(queue == NULL) {
        perror(" - ERROR: queue allocation failed.");
        exit(EXIT_FAILURE);
    }

    queue->front = NULL;
    queue->rear = NULL;
    queue->size = 0;
    queue->capacity = capacity;

    return queue;
}

void queue_destroy(Queue *queue) {
    if(queue == NULL) {
        return;
    }

    Node *curr = queue->front;
    while(curr) {
        Node *temp = curr;
        curr = curr->prev;
        free(temp);
    }

    free(queue);
}

bool queue_empty(Queue *queue) {
    assert(queue != NULL);
    return queue->size == 0;
}

bool queue_full(Queue *queue) {
    assert(queue != NULL);
    return queue->size == queue->capacity;
}

bool queue_push(Queue *queue, Task *task) {
    assert(queue != NULL);
    if(queue_full(queue)) {
        puts(" - ERROR: queue is full.");
        return false;
    }

    Node *new_node = (Node*)malloc(sizeof(Node));
    if(new_node == NULL) {
        perror(" - ERROR: node allocation failed.");
        return false;
    }
    new_node->prev = NULL;
    new_node->task = (Task *)task;

    if(queue_empty(queue)) {
        queue->rear = queue->front = new_node;
        queue->rear->prev = queue->front->prev = NULL;
        queue->rear->next = queue->front->next = NULL;
    } 
    else {
        new_node->next = queue->rear;
        queue->rear->prev = new_node;
        queue->rear = new_node;
    }
    ++queue->size;
    return true;
}

Task *queue_pop(Queue *queue) { 
    assert(queue != NULL);
    if(queue_empty(queue)) {
        puts(" - ERROR: queue is empty.");
        return NULL;
    }

    Node *target_node = queue->front;
    Task *task = target_node->task;
    queue->front = queue->front->prev;
    if(queue->front != NULL) queue->front->next = NULL;    //! 队列只有一个元素时注意
    --queue->size;
    free(target_node);
    return task;
}
